package com.ce.util;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.ce.framework.datamaintain.logic.ISQLMapper;
import com.ce.framework.util.StringUtil;
import com.ce.sys.menu.dao.po.SysMenuOperations;
import com.ce.sys.menu.view.SysMenuInfo;

/**
 * 嫦娥软件有限公司 版权所有 2013
 * 创建人： andy
 * 创建时间： 2013-11-1 上午09:47:59
 * 功能描述：菜单工具类，通过URL在缓存中获取菜单id
 * ==================================
 * 修改历史
 * 修改人        修改时间      修改位置（函数名）
 *
 * ==================================
 */
public class MenuUtil {

	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-1 上午09:48:41
	 * 功能描述：获取菜单缓存
	 * 方法的参数和返回值
	 * @return
	 * Map<String,String> 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String,String> getMenuCache(){
		Map map = CacheUtil.getCacheMap(CacheUtil.MENU_CACHE);
		return (Map<String,String>)map;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String,SysMenuInfo> getMenuOptCache(){
		Map map = CacheUtil.getCacheMap(CacheUtil.MENU_OPT_CACHE);
		return (Map<String,SysMenuInfo>)map;
	}
	
	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-1 上午09:48:55
	 * 功能描述：根据菜单url获取菜单id
	 * 方法的参数和返回值
	 * @param menuUrl
	 * @return
	 * String 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	private static String EMPTY_ID = "    ";
	public static String getMenuId(String menuUrl){
		if(StringUtil.isBlank(menuUrl)){
			return null;
		}
		Map<String,String> map = getMenuCache();
		String value = map.get(menuUrl);
		if(value!=null){
			if(value==EMPTY_ID){
				return null;
			}
			return value;
		}
		String sql = "select vc_id from  sys_t_menu t where t.vc_del$flag = 0 and t.int_level =0 and t.vc_url='"+menuUrl+"'";
		value = DbUtil.getFirstStringSqlQuery(sql);
		if(value==null&&menuUrl.indexOf("?")>0){//如果在菜单中没有找到，并且URL中带有参数，把参数去掉后再次查找
			value = getMenuId(menuUrl.substring(0,menuUrl.indexOf("?")));
		}
		if(value==null)
			value = EMPTY_ID;
		map.put(menuUrl, value);
		if(value==EMPTY_ID){
			return null;
		}
		return value;
	}
	
	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-2 上午10:17:13
	 * 功能描述：获取某个菜单所具有的所有操作功能
	 * 方法的参数和返回值
	 * @param menuId
	 * @return
	 * String 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	@SuppressWarnings("rawtypes")
	public static String getMenuAllOpts(String menuId){
		Map<String,String> map = getMenuCache();
		String value = map.get(menuId);
		if(value!=null)return value;
		List optList = DbUtil.executeHql("from SysMenuOperations po where po.vcMenuId = '"+menuId+"' and po.vcDelFlag = 0");
		Iterator it = optList.iterator();
		while(it.hasNext()){
			SysMenuOperations opt = (SysMenuOperations)it.next();
			value = value + opt.getVcSimpleName()+",";
		}
		if(value==null)
			value = "";
		map.put(menuId, value);
		return value;
	}
	
	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-1 上午09:49:11
	 * 功能描述：清除菜单缓存
	 * 方法的参数和返回值
	 * void 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	public static void clearValues(){
		CacheUtil.clearCache(CacheUtil.MENU_CACHE);
		CacheUtil.clearCache(CacheUtil.MENU_OPT_CACHE);
	}
	
	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-22 下午02:31:06
	 * 功能描述：根据URL获取访问该URL所要实现的操作功能。
	 *         如类似xxx.action的地址返回 "",
	 *         如类似xxx_add.action的地址返回 "add",
	 * 方法的参数和返回值
	 * @param url
	 * @return
	 * String 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	public static String analyseUrlToOperator(String url){
		String authOp = "";
		int pos = url.indexOf("_");
		if(pos>0&&url.indexOf(".action")>pos){
			//当访问地址是形如"name_auth.action"时，获取auth字符串
			authOp = url.substring(url.indexOf("_")+1,url.indexOf(".action"));
		}
		return authOp;
	}

	
	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-22 下午03:19:26
	 * 功能描述：根据指定的URL地址，解析成对应菜单的URL
	 * 算法描述：由于系统中存入的菜单地址都形如"name.action"或"name.action?xx=aa"，
	 *         而获取的url可能为"name_auth.action?op=aa"或"name_auth.action?op=aa&xx=bb"，因此需要对URL进行转化
			   把类似"name_auth.action?op=aa&xx=bb"的地址都转化为"name.action?xx=bb"形式，即取消action中的auth转向方法和默认的op参数及参数值
	 * 方法的参数和返回值
	 * @param url
	 * @return
	 * String 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	public static String analyseUrlToMenuUrl(String url){
		//如果获取的url带有参数，则将?分隔符替换成&，并按&分割
		if(url.indexOf("?")>0){
			String front = url.substring(0,url.indexOf("?"));  //url前半部分
			String back = url.substring(url.indexOf("?")+1,url.length());   //url后半部分
			front = front.replaceAll("_"+MenuUtil.analyseUrlToOperator(front), ""); //将前半部分进行转换
			int pos = back.indexOf("&&");//URL中&&及其后的内容不做为菜单URL进行权限识别
			if(pos==0){
				back = "";
			}
			else if(pos>0){
				back = "?"+back.substring(0,pos);
			}else if(pos<0){
				back = "?"+back;
			}
			url = front + back;
		}else{
			if(url.indexOf("_")>0){
				url = url.replaceAll("_"+MenuUtil.analyseUrlToOperator(url), "");
			}
		}
		return url;
	}
	
	/**
	 * 开发人： andy
	 * 开发时间： 2013-11-24 下午03:16:59
	 * 功能描述：根据访问的URL地址获取该地址对应的菜单信息，即该菜单的名称和对菜单的操作名称
	 * 方法的参数和返回值
	 * @param url
	 * @return
	 * SysMenuInfo 菜单信息
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 */
	public static SysMenuInfo getMenuInfoByUrl(String url){
		String menuUrl = MenuUtil.analyseUrlToMenuUrl(url);
		String menuOpt = MenuUtil.analyseUrlToOperator(url);
		String menuId = getMenuId(menuUrl);
		final String key = menuId+"||"+menuOpt;	
		final Map<String,SysMenuInfo> map = getMenuOptCache();
		SysMenuInfo res = map.get(key);
		if(res!=null){//优先从缓存中取
			if(res==SysMenuInfo.EMPTY){
				return null;
			}
			return res;
		}
		if("loginOut".equals(menuOpt)){
			SysMenuInfo info = new SysMenuInfo();
			info.setMenuName("系统登录");
			info.setMenuOptName("退出");
			return info;
		}else if("enterMainFrame".equals(menuOpt)){
			SysMenuInfo info = new SysMenuInfo();
			info.setMenuName("系统登录");
			info.setMenuOptName("登录");
			return info;
		}
		String sql = "";
		if(StringUtil.isBlank(menuOpt)){
			//当菜单操作为空时，默认操作为查询或查查操作
			sql = "select m.vc_name, '查询或查看' as optname,m.vc_id  from sys_t_menu m where m.vc_id = '"+menuId+"' and m.vc_del$flag = 0";
		}else if(url.indexOf("op=save")>=0||url.indexOf("op=del")>=0){
			//当url地址带op参数时，根据参数值确定该操作是更新数据库的操作
			sql = "select m.vc_name,p.vc_name as optname,m.vc_id from sys_t_menu m, sys_t_menu$operations p" +
			" where m.vc_id = p.vc_menu$id(+) and p.vc_del$flag =0 and p.vc_simple$name ='"+menuOpt+"' and m.vc_id='"+menuId+"'";
		}else{
			//当url地址不带op参数时，确定该操作为打开xx页面的操作
			sql = "select m.vc_name,'打开'||p.vc_name||'页面' as optname,m.vc_id from sys_t_menu m, sys_t_menu$operations p" +
			" where m.vc_id = p.vc_menu$id(+) and p.vc_del$flag =0 and p.vc_simple$name ='"+menuOpt+"' and m.vc_id='"+menuId+"'";
		}

		List<?> infoList = DbUtil.executeSqlQuery(sql, new ISQLMapper(){
			public Object fromSQLQuery(ResultSet rs, int num) {
				// TODO Auto-generated method stub
				SysMenuInfo info = new SysMenuInfo();
				try {
					info.setMenuName(rs.getString("vc_name"));
					info.setMenuOptName(rs.getString("optname"));
					info.setVcId(rs.getString("vc_id"));
				} catch (SQLException e) {
				   e.printStackTrace();
				   Logger.getLogger(this.getClass()).error("获取菜单信息失败！");
				}
				map.put(key, info);
				return info;
			}
		});
		if(infoList!=null&&infoList.size()>0){
			map.put(key, (SysMenuInfo) infoList.get(0));
			return (SysMenuInfo) infoList.get(0);
		}
		map.put(key, SysMenuInfo.EMPTY);
		return null;
	}
}
